#region (c) 2014 THN Solutions LLC. - All rights reserved
/*
Simplified BSD License (BSD)
Copyright (c) 2014, THN Solutions LLC. ( www.ThnSolutions.com )
Author: Nguyễn, M. Hải                 ( www.Minh-Hai.com     )
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this 
      list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright notice, 
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
POSSIBILITY OF SUCH DAMAGE.
*/
#endregion

#region Record of Change
//             							CHANGE HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | DEVELOPER  | DESCRIPTION                                              |
// -------------------------------------------------------------------------------------
// | 26-Nov-09 | HaiNM      | First creation.                                          |
// -------------------------------------------------------------------------------------
//
#endregion

#region Record of Audit
//             							REVIEW HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | REVIEWER   | NOTES                                                    |
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
//
#endregion

#region Using directives
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.ComponentModel;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using VS = System.Windows.Forms.VisualStyles;

using Thn;
using Thn.Interface.Vcl;
#endregion

namespace Thn.Interface.Vcl
{
    /*
     * This control was based on the work of: Lukasz Swiatkowski
     * http://lukesw.net/articles/SimplePopup.aspx
     */
    /// <summary>
    /// This is a helper class for showing popups. This class is deliberately set to internal because it is a wrapper around the
    /// <see cref="System.Windows.Forms.ToolStripDropDown"/>
    /// </summary>
    [CLSCompliant(true), ToolboxItem(false)]
#if DEBUG
    internal
#else
    internal
#endif
    partial class NativePopup : ToolStripDropDown
    {
        #region Fields

        private Control mOpener;
        private NativePopup mOwnerPopup;
        private NativePopup mChildPopup;
        private bool mResizableTop;
        private bool mResizableLeft;

        private bool mIsChildPopupOpened;
        private ToolStripControlHost mHost;

        #endregion

        #region Properties

        #region Content
        private Control mContent;
        /// <summary>
        /// Gets/Sets the content of the pop-up.
        /// </summary>
        [Browsable(true), DefaultValue(null), Category("Data"), Description("Content of the popup")]
        public Control Content
        {
            get { return mContent; }
            set { mContent = value; }
        }
        #endregion

        #region Showing Animation
        private PopupAnimations mShowingAnimation = PopupAnimations.SystemDefault;
        /// <summary>
        /// Gets/Sets animation style to apply while showing the pop-up windows.
        /// </summary>
        [Browsable(true), DefaultValue(PopupAnimations.SystemDefault), Category("Appearance"), Description("Animation style for showing the pop-up windows.")]
        public PopupAnimations ShowingAnimation
        {
            get { return mShowingAnimation; }
            set { mShowingAnimation = value; }
        }
        #endregion

        #region Hiding Animation
        private PopupAnimations mHidingAnimation = PopupAnimations.None;
        /// <summary>
        /// Gets/Sets animation style to apply while hiding the pop-up windows.
        /// </summary>
        [Browsable(true), DefaultValue(PopupAnimations.None), Category("Appearance"), Description("Animation style for hiding the pop-up windows.")]
        public PopupAnimations HidingAnimation
        {
            get { return mHidingAnimation; }
            set { mHidingAnimation = value; }
        }
        #endregion

        #region Animation Duration
        private int mAnimationDuration = 100;
        /// <summary>
        /// Gets/Sets the duration (in milliseconds) for animation effects.
        /// </summary>
        [Browsable(true), DefaultValue(100), Category("Appearance"), Description("Duration (in ms.) for animation effects.")]
        public int AnimationDuration
        {
            get { return mAnimationDuration; }
            set { mAnimationDuration = value; }
        }
        #endregion

        #region Focus On Open
        private bool mFocusOnOpen = true;
        /// <summary>
        /// Gets or sets a value indicating whether the content should receive the focus after the pop-up has been opened.
        /// </summary>
        /// <value><c>true</c> if the content should be focused after the pop-up has been opened; otherwise, <c>false</c>.</value>
        /// <remarks>If the FocusOnOpen property is set to <c>false</c>, then pop-up cannot use the fade effect.</remarks>
        [Browsable(true), DefaultValue(true), Category("Behavior"), Description("Whether content should receive focus when pop-up is opened.")]
        public bool FocusOnOpen
        {
            get { return mFocusOnOpen; }
            set { mFocusOnOpen = value; }
        }
        #endregion

        #region Accept Alt
        private bool mAcceptAlt = true;
        /// <summary>
        /// Gets or sets a value indicating whether presing the alt key should close the pop-up.
        /// </summary>
        /// <value><c>true</c> if presing the alt key does not close the pop-up; otherwise, <c>false</c>.</value>
        [Browsable(true), DefaultValue(true), Category("Behavior"), Description("Whether pressing the Alt key should close the pop-up.")]
        public bool AcceptAlt
        {
            get { return mAcceptAlt; }
            set { mAcceptAlt = value; }
        }
        #endregion

        #region Resizable
        private bool mResizable;
        /// <summary>
        /// Gets or sets a value indicating whether the <see cref="PopupControl.Popup" /> is resizable.
        /// </summary>
        /// <value><c>true</c> if resizable; otherwise, <c>false</c>.</value>
        [Browsable(true), DefaultValue(false), Category("Behavior"), Description("Whether the pop-up form is resizable.")]
        public bool Resizable
        {
            get { return mResizable && !mIsChildPopupOpened; }
            set { mResizable = value; }
        }
        #endregion

        #region Minimum Size
        private Size mMinimumSize;
        /// <summary>
        /// Gets or sets a minimum size of the pop-up.
        /// </summary>
        /// <returns>An ordered pair of type <see cref="T:System.Drawing.Size" /> representing the width and height of a rectangle.</returns>
        [Browsable(true), Category("Appearance"), Description("Minimum size of the pop-up.")]
        public new Size MinimumSize
        {
            get { return mMinimumSize; }
            set { mMinimumSize = value; }
        }
        #endregion

        #region Maximum Size
        private Size mMaximumSize;
        /// <summary>
        /// Gets or sets a maximum size of the pop-up.
        /// </summary>
        /// <returns>An ordered pair of type <see cref="T:System.Drawing.Size" /> representing the width and height of a rectangle.</returns>
        [Browsable(true), Category("Appearance"), Description("Maximum size of the pop-up.")]
        public new Size MaximumSize
        {
            get { return mMaximumSize; }
            set { mMaximumSize = value; }
        }
        #endregion

        #endregion

        #region Show
        /// <summary>
        /// Shows the pop-up window below the specified control.
        /// </summary>
        /// <param name="control">The control below which the pop-up will be shown.</param>
        /// <remarks>
        /// When there is no space below the specified control, the pop-up control is shown above it.
        /// </remarks>
        /// <exception cref="T:System.ArgumentNullException"><paramref name="control"/> is <code>null</code>.</exception>
        public void Show(Control control)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }
            Show(control, control.ClientRectangle);
        }

        /// <summary>
        /// Shows the pop-up window below the specified area of the specified control.
        /// </summary>
        /// <param name="control">The control used to compute screen location of specified area.</param>
        /// <param name="area">The area of control below which the pop-up will be shown.</param>
        /// <remarks>
        /// When there is no space below specified area, the pop-up control is shown above it.
        /// </remarks>
        /// <exception cref="T:System.ArgumentNullException"><paramref name="control"/> is <code>null</code>.</exception>
        public void Show(Control control, Rectangle area)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }
            SetOwnerItem(control);

            mResizableTop = mResizableLeft = false;
            Point location = control.PointToScreen(new Point(area.Left, area.Top + area.Height));
            Rectangle screen = Screen.FromControl(control).WorkingArea;
            if (location.X + Size.Width > (screen.Left + screen.Width))
            {
                mResizableLeft = true;
                location.X = (screen.Left + screen.Width) - Size.Width;
            }
            if (location.Y + Size.Height > (screen.Top + screen.Height))
            {
                mResizableTop = true;
                location.Y -= Size.Height + area.Height;
            }
            location = control.PointToClient(location);
            Show(control, location, ToolStripDropDownDirection.BelowRight);
        }
        #endregion

        #region Set Owner Item
        private void SetOwnerItem(Control control)
        {
            if (control == null)
            {
                return;
            }
            if (control is NativePopup)
            {
                NativePopup popupControl = control as NativePopup;
                mOwnerPopup = popupControl;
                mOwnerPopup.mChildPopup = this;
                OwnerItem = popupControl.Items[0];
                return;
            }
            else if (mOpener == null)
            {
                mOpener = control;
            }
            if (control.Parent != null)
            {
                SetOwnerItem(control.Parent);
            }
        }
        #endregion

        #region Create Params
        /// <summary>
        /// Gets parameters of a new window.
        /// </summary>
        /// <returns>An object of type <see cref="T:System.Windows.Forms.CreateParams" /> used when creating a new window.</returns>
        protected override CreateParams CreateParams
        {
            [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= PopupNativeMethods.WS_EX_NOACTIVATE;
                return cp;
            }
        }
        #endregion

        #region On Visible Changed
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.ToolStripItem.VisibleChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnVisibleChanged(EventArgs e)
        {
            base.OnVisibleChanged(e);
            if ((Visible && ShowingAnimation == PopupAnimations.None) || (!Visible && HidingAnimation == PopupAnimations.None))
            {
                return;
            }
            PopupNativeMethods.AnimationFlags flags = Visible ? PopupNativeMethods.AnimationFlags.Roll : PopupNativeMethods.AnimationFlags.Hide;
            PopupAnimations _flags = Visible ? ShowingAnimation : HidingAnimation;
            if (_flags == PopupAnimations.SystemDefault)
            {
                if (SystemInformation.IsMenuAnimationEnabled)
                {
                    if (SystemInformation.IsMenuFadeEnabled)
                    {
                        _flags = PopupAnimations.Blend;
                    }
                    else
                    {
                        _flags = PopupAnimations.Slide | (Visible ? PopupAnimations.TopToBottom : PopupAnimations.BottomToTop);
                    }
                }
                else
                {
                    _flags = PopupAnimations.None;
                }
            }
            if ((_flags & (PopupAnimations.Blend | PopupAnimations.Center | PopupAnimations.Roll | PopupAnimations.Slide)) == PopupAnimations.None)
            {
                return;
            }
            if (mResizableTop) // popup is “inverted”, so the animation must be
            {
                if ((_flags & PopupAnimations.BottomToTop) != PopupAnimations.None)
                {
                    _flags = (_flags & ~PopupAnimations.BottomToTop) | PopupAnimations.TopToBottom;
                }
                else if ((_flags & PopupAnimations.TopToBottom) != PopupAnimations.None)
                {
                    _flags = (_flags & ~PopupAnimations.TopToBottom) | PopupAnimations.BottomToTop;
                }
            }
            if (mResizableLeft) // popup is “inverted”, so the animation must be
            {
                if ((_flags & PopupAnimations.RightToLeft) != PopupAnimations.None)
                {
                    _flags = (_flags & ~PopupAnimations.RightToLeft) | PopupAnimations.LeftToRight;
                }
                else if ((_flags & PopupAnimations.LeftToRight) != PopupAnimations.None)
                {
                    _flags = (_flags & ~PopupAnimations.LeftToRight) | PopupAnimations.RightToLeft;
                }
            }
            flags = flags | (PopupNativeMethods.AnimationFlags.Mask & (PopupNativeMethods.AnimationFlags)(int)_flags);
            PopupNativeMethods.AnimateWindow(this, AnimationDuration, flags);
        }
        #endregion

        #region Process Dialog Key
        /// <summary>
        /// Processes a dialog box key.
        /// </summary>
        /// <param name="keyData">One of the <see cref="T:System.Windows.Forms.Keys" /> values that represents the key to process.</param>
        /// <returns>
        /// true if the key was processed by the control; otherwise, false.
        /// </returns>
        [UIPermission(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (mAcceptAlt && ((keyData & Keys.Alt) == Keys.Alt))
            {
                if ((keyData & Keys.F4) != Keys.F4)
                {
                    return false;
                }
                else
                {
                    this.Close();
                }
            }
            bool processed = base.ProcessDialogKey(keyData);
            if (!processed && (keyData == Keys.Tab || keyData == (Keys.Tab | Keys.Shift)))
            {
                bool backward = (keyData & Keys.Shift) == Keys.Shift;
                this.Content.SelectNextControl(null, !backward, true, true, true);
            }
            return processed;
        }
        #endregion

        #region Update Region
        /// <summary>
        /// Updates the pop-up region.
        /// </summary>
        protected void UpdateRegion()
        {
            if (this.Region != null)
            {
                this.Region.Dispose();
                this.Region = null;
            }
            if (mContent.Region != null)
            {
                this.Region = mContent.Region.Clone();
            }
        }
        #endregion

        #region On Size Changed
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.SizeChanged" /> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
        protected override void OnSizeChanged(EventArgs e)
        {
            mContent.MinimumSize = Size;
            mContent.MaximumSize = Size;
            mContent.Size = Size;
            mContent.Location = Point.Empty;
            base.OnSizeChanged(e);
        }
        #endregion

        #region On Opening
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.ToolStripDropDown.Opening" /> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.ComponentModel.CancelEventArgs" /> that contains the event data.</param>
        protected override void OnOpening(CancelEventArgs e)
        {
            if (mContent.IsDisposed || mContent.Disposing)
            {
                e.Cancel = true;
                return;
            }
            UpdateRegion();
            base.OnOpening(e);
        }
        #endregion

        #region On Opened
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.ToolStripDropDown.Opened" /> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
        protected override void OnOpened(EventArgs e)
        {
            if (mOwnerPopup != null)
            {
                mOwnerPopup.mIsChildPopupOpened = true;
            }
            if (mFocusOnOpen)
            {
                mContent.Focus();
            }
            base.OnOpened(e);
        }
        #endregion

        #region On Closed
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.ToolStripDropDown.Closed"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.ToolStripDropDownClosedEventArgs"/> that contains the event data.</param>
        protected override void OnClosed(ToolStripDropDownClosedEventArgs e)
        {
            mOpener = null;
            if (mOwnerPopup != null)
            {
                mOwnerPopup.mIsChildPopupOpened = false;
            }
            base.OnClosed(e);
        }
        #endregion

        #region " Resizing Support "

        /// <summary>
        /// Processes Windows messages.
        /// </summary>
        /// <param name="m">The Windows <see cref="T:System.Windows.Forms.Message" /> to process.</param>
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        protected override void WndProc(ref Message m)
        {
            //if (m.Msg == NativeMethods.WM_PRINT && !Visible)
            //{
            //    Visible = true;
            //}
            if (InternalProcessResizing(ref m, false))
            {
                return;
            }
            base.WndProc(ref m);
        }

        /// <summary>
        /// Processes the resizing messages.
        /// </summary>
        /// <param name="m">The message.</param>
        /// <returns>true, if the WndProc method from the base class shouldn't be invoked.</returns>
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        public bool ProcessResizing(ref Message m)
        {
            return InternalProcessResizing(ref m, true);
        }

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        private bool InternalProcessResizing(ref Message m, bool contentControl)
        {
            if (m.Msg == PopupNativeMethods.WM_NCACTIVATE && m.WParam != IntPtr.Zero && mChildPopup != null && mChildPopup.Visible)
            {
                mChildPopup.Hide();
            }
            if (!Resizable)
            {
                return false;
            }
            if (m.Msg == PopupNativeMethods.WM_NCHITTEST)
            {
                return OnNcHitTest(ref m, contentControl);
            }
            else if (m.Msg == PopupNativeMethods.WM_GETMINMAXINFO)
            {
                return OnGetMinMaxInfo(ref m);
            }
            return false;
        }

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        private bool OnGetMinMaxInfo(ref Message m)
        {
            PopupNativeMethods.MINMAXINFO minmax = (PopupNativeMethods.MINMAXINFO)Marshal.PtrToStructure(m.LParam, typeof(PopupNativeMethods.MINMAXINFO));
            if (!this.MaximumSize.IsEmpty)
            {
                minmax.maxTrackSize = this.MaximumSize;
            }
            minmax.minTrackSize = this.MinimumSize;
            Marshal.StructureToPtr(minmax, m.LParam, false);
            return true;
        }

        private bool OnNcHitTest(ref Message m, bool contentControl)
        {
            int x = PopupNativeMethods.LOWORD(m.LParam);
            int y = PopupNativeMethods.HIWORD(m.LParam);
            Point clientLocation = PointToClient(new Point(x, y));

            PopupGripBounds gripBouns = new PopupGripBounds(contentControl ? mContent.ClientRectangle : ClientRectangle);
            IntPtr transparent = new IntPtr(PopupNativeMethods.HTTRANSPARENT);

            if (mResizableTop)
            {
                if (mResizableLeft && gripBouns.TopLeft.Contains(clientLocation))
                {
                    m.Result = contentControl ? transparent : (IntPtr)PopupNativeMethods.HTTOPLEFT;
                    return true;
                }
                if (!mResizableLeft && gripBouns.TopRight.Contains(clientLocation))
                {
                    m.Result = contentControl ? transparent : (IntPtr)PopupNativeMethods.HTTOPRIGHT;
                    return true;
                }
                if (gripBouns.Top.Contains(clientLocation))
                {
                    m.Result = contentControl ? transparent : (IntPtr)PopupNativeMethods.HTTOP;
                    return true;
                }
            }
            else
            {
                if (mResizableLeft && gripBouns.BottomLeft.Contains(clientLocation))
                {
                    m.Result = contentControl ? transparent : (IntPtr)PopupNativeMethods.HTBOTTOMLEFT;
                    return true;
                }
                if (!mResizableLeft && gripBouns.BottomRight.Contains(clientLocation))
                {
                    m.Result = contentControl ? transparent : (IntPtr)PopupNativeMethods.HTBOTTOMRIGHT;
                    return true;
                }
                if (gripBouns.Bottom.Contains(clientLocation))
                {
                    m.Result = contentControl ? transparent : (IntPtr)PopupNativeMethods.HTBOTTOM;
                    return true;
                }
            }
            if (mResizableLeft && gripBouns.Left.Contains(clientLocation))
            {
                m.Result = contentControl ? transparent : (IntPtr)PopupNativeMethods.HTLEFT;
                return true;
            }
            if (!mResizableLeft && gripBouns.Right.Contains(clientLocation))
            {
                m.Result = contentControl ? transparent : (IntPtr)PopupNativeMethods.HTRIGHT;
                return true;
            }
            return false;
        }

        private VS.VisualStyleRenderer sizeGripRenderer;
        /// <summary>
        /// Paints the sizing grip.
        /// </summary>
        /// <param name="e">The <see cref="System.Windows.Forms.PaintEventArgs" /> instance containing the event data.</param>
        public void PaintSizeGrip(PaintEventArgs e)
        {
            if (e == null || e.Graphics == null || !mResizable)
            {
                return;
            }
            Size clientSize = mContent.ClientSize;
            using (Bitmap gripImage = new Bitmap(0x10, 0x10))
            {
                using (Graphics g = Graphics.FromImage(gripImage))
                {
                    if (System.Windows.Forms.Application.RenderWithVisualStyles)
                    {
                        if (this.sizeGripRenderer == null)
                        {
                            this.sizeGripRenderer = new VS.VisualStyleRenderer(VS.VisualStyleElement.Status.Gripper.Normal);
                        }
                        this.sizeGripRenderer.DrawBackground(g, new Rectangle(0, 0, 0x10, 0x10));
                    }
                    else
                    {
                        ControlPaint.DrawSizeGrip(g, mContent.BackColor, 0, 0, 0x10, 0x10);
                    }
                }
                GraphicsState gs = e.Graphics.Save();
                e.Graphics.ResetTransform();
                if (mResizableTop)
                {
                    if (mResizableLeft)
                    {
                        e.Graphics.RotateTransform(180);
                        e.Graphics.TranslateTransform(-clientSize.Width, -clientSize.Height);
                    }
                    else
                    {
                        e.Graphics.ScaleTransform(1, -1);
                        e.Graphics.TranslateTransform(0, -clientSize.Height);
                    }
                }
                else if (mResizableLeft)
                {
                    e.Graphics.ScaleTransform(-1, 1);
                    e.Graphics.TranslateTransform(-clientSize.Width, 0);
                }
                e.Graphics.DrawImage(gripImage, clientSize.Width - 0x10, clientSize.Height - 0x10 + 1, 0x10, 0x10);
                e.Graphics.Restore(gs);
            }
        }

        #endregion

        #region Constructors
        /// <summary>
        /// Default constructor.
        /// </summary>
        public NativePopup(Control content)
        {
            if (content == null)
            {
                throw new ArgumentNullException("content");
            }
            mContent = content;
            mShowingAnimation = PopupAnimations.SystemDefault;
            mHidingAnimation = PopupAnimations.None;
            mAnimationDuration = 100;
            mIsChildPopupOpened = false;
            InitializeComponent();
            AutoSize = false;
            DoubleBuffered = true;
            ResizeRedraw = true;
            mHost = new ToolStripControlHost(content);
            Padding = Margin = mHost.Padding = mHost.Margin = Padding.Empty;
            MinimumSize = content.MinimumSize;
            content.MinimumSize = content.Size;
            MaximumSize = content.MaximumSize;
            content.MaximumSize = content.Size;
            Size = content.Size;
            TabStop = content.TabStop = true;
            content.Location = Point.Empty;
            Items.Add(mHost);
            content.Disposed += delegate(object sender, EventArgs e)
            {
                content = null;
                Dispose(true);
            };
            content.RegionChanged += delegate(object sender, EventArgs e)
            {
                UpdateRegion();
            };
            content.Paint += delegate(object sender, PaintEventArgs e)
            {
                PaintSizeGrip(e);
            };
            UpdateRegion();
        }
        #endregion
    }
}
